import { create } from 'zustand';
import {
    type Connection,
    type Edge,
    type EdgeChange,
    type Node,
    type NodeChange,
    addEdge,
    applyNodeChanges,
    applyEdgeChanges,
} from '@xyflow/react';
import type { BehaviorTreeNode, NodeData } from '../types/behaviorTree';
import { validateTree, type ValidationError } from '../utils/validator';
import { getLayoutedElements } from '../utils/layout';
import { debounce } from '../utils/debounce';

// 定义设置接口
interface EditorSettings {
    autoSave: boolean;
    theme: 'light' | 'dark';
    language: 'zh' | 'en';
    showMinimap: boolean;
}

// 默认设置
const DEFAULT_SETTINGS: EditorSettings = {
    autoSave: true,
    theme: 'light',
    language: 'zh',
    showMinimap: true,
};

/**
 * @interface FlowState
 * @description 定义了 Zustand store 的状态接口，包含节点、边和操作函数。
 */
interface FlowState {
    nodes: Node<NodeData>[];
    edges: Edge[];
    selectedNodeId: string | null;
    errors: ValidationError[];
    settings: EditorSettings; // 新增：编辑器设置
    /**
     * @function onNodesChange
     * @description 处理节点变化的函数，用于更新 store 中的节点状态。
     * @param {NodeChange[]} changes - 节点变化的数组。
     */
    onNodesChange: (changes: NodeChange[]) => void;
    /**
     * @function onEdgesChange
     * @description 处理边变化的函数，用于更新 store 中的边状态。
     * @param {EdgeChange[]} changes - 边变化的数组。
     */
    onEdgesChange: (changes: EdgeChange[]) => void;
    /**
     * @function onConnect
     * @description 处理节点连接的函数，用于在 store 中添加新的边。
     * @param {Connection} connection - 新连接的信息。
     */
    onConnect: (connection: Connection) => void;
    /**
     * @function setNodes
     * @description 设置 store 中的节点数组。
     * @param {Node<NodeData>[]} nodes - 新的节点数组。
     */
    setNodes: (nodes: Node<NodeData>[]) => void;
    /**
     * @function setEdges
     * @description 设置 store 中的边数组。
     * @param {Edge[]} edges - 新的边数组。
     */
    setEdges: (edges: Edge[]) => void;
    /**
     * @function addNode
     * @description 向 store 中添加一个新节点。
     * @param {BehaviorTreeNode} newNode - 要添加的新节点。
     */
    addNode: (newNode: BehaviorTreeNode) => void;
    /**
     * @function setSelectedNodeId
     * @description 设置当前选中的节点ID。
     * @param {string | null} nodeId - 选中的节点ID，如果没有选中则为 null。
     */
    setSelectedNodeId: (nodeId: string | null) => void;
    /**
     * @function updateNodeData
     * @description 更新指定节点的data属性。
     * @param {string} nodeId - 要更新的节点ID。
     * @param {Partial<NodeData>} newData - 要合并到节点data中的新数据。
     */
    updateNodeData: (nodeId: string, newData: Partial<NodeData>) => void;
    /**
     * @function applyLayout
     * @description 对行为树节点应用自动布局，并更新 store 中的节点位置。
     */
    applyLayout: () => void;
    /**
     * @function updateSettings
     * @description 更新编辑器设置。
     * @param {Partial<EditorSettings>} newSettings - 要更新的设置。
     */
    updateSettings: (newSettings: Partial<EditorSettings>) => void; // 新增：更新设置的函数
}

/**
 * @function useFlowStore
 * @description 创建并导出 React Flow 的 Zustand store。
 * 该 store 管理画布上的节点和边，并提供相应的操作函数。
 */
export const useFlowStore = create<FlowState>((set) => {
    // 延迟验证函数，300ms 防抖
    const debouncedValidate = debounce((nodes: BehaviorTreeNode[], edges: Edge[]) => {
        const newErrors = validateTree(nodes, edges);
        set((state) => ({ ...state, errors: newErrors }));
    }, 300);

    return {
        nodes: [],
        edges: [],
        selectedNodeId: null,
        errors: [],
        settings: DEFAULT_SETTINGS, // 初始化设置
        /**
         * @function onNodesChange
         * @description React Flow 节点变化的回调函数，用于更新 Zustand store 中的节点状态。
         *              对于位置变化使用延迟验证，对于添加/删除节点立即验证。
         * @param {NodeChange[]} changes - 节点变化的数组。
         */
        onNodesChange: (changes: NodeChange[]) => {
            set((state) => {
                const newNodes = applyNodeChanges(changes, state.nodes) as Node<NodeData>[];
                
                // 检查是否有非位置变化（如添加、删除节点）
                const hasStructuralChange = changes.some(
                    (change) => change.type !== 'position' && change.type !== 'dimensions'
                );
                
                if (hasStructuralChange) {
                    // 结构性变化立即验证
                    const newErrors = validateTree(newNodes as BehaviorTreeNode[], state.edges);
                    return {
                        nodes: newNodes,
                        errors: newErrors,
                    };
                } else {
                    // 仅位置变化，使用延迟验证
                    debouncedValidate(newNodes as BehaviorTreeNode[], state.edges);
                    return { nodes: newNodes };
                }
            });
        },
        /**
         * @function onEdgesChange
         * @description React Flow 边变化的回调函数，用于更新 Zustand store 中的边状态。
         *              每次边变化后，都会重新验证行为树的结构。
         * @param {EdgeChange[]} changes - 边变化的数组。
         */
        onEdgesChange: (changes: EdgeChange[]) => {
        set((state) => {
            const newEdges = applyEdgeChanges(changes, state.edges) as Edge[];
            // 类型断言：确保传入 validateTree 的 nodes 符合 BehaviorTreeNode[] 类型
            const newErrors = validateTree(state.nodes as BehaviorTreeNode[], newEdges);
            return {
                edges: newEdges,
                errors: newErrors,
            };
        });
        },
        /**
         * @function onConnect
         * @description React Flow 建立新连接的回调函数，用于在 Zustand store 中添加新的边。
         *              添加新连接后，会重新验证行为树的结构。
         * @param {Connection} connection - 新连接的信息。
         */
        onConnect: (connection: Connection) => {
        set((state) => {
            const newEdges = addEdge(connection, state.edges);
            // 类型断言：确保传入 validateTree 的 nodes 符合 BehaviorTreeNode[] 类型
            const newErrors = validateTree(state.nodes as BehaviorTreeNode[], newEdges);
            return {
                edges: newEdges,
                errors: newErrors,
            };
        });
        },
        /**
         * @function setNodes
         * @description 直接设置 Zustand store 中的节点数组，用于导入等场景。
         *              设置节点后，会重新验证行为树的结构。
         * @param {Node<NodeData>[]} nodes - 新的节点数组。
         */
        setNodes: (nodes: Node<NodeData>[]) => {
        set((state) => {
            // 类型断言：确保传入 validateTree 的 nodes 符合 BehaviorTreeNode[] 类型
            const newErrors = validateTree(nodes as BehaviorTreeNode[], state.edges);
            return { nodes, errors: newErrors };
        });
        },
        /**
         * @function setEdges
         * @description 直接设置 Zustand store 中的边数组，用于导入等场景。
         *              设置边后，会重新验证行为树的结构。
         * @param {Edge[]} edges - 新的边数组。
         */
        setEdges: (edges: Edge[]) => {
        set((state) => {
            // 类型断言：确保传入 validateTree 的 nodes 符合 BehaviorTreeNode[] 类型
            const newErrors = validateTree(state.nodes as BehaviorTreeNode[], edges);
            return { edges, errors: newErrors };
        });
        },
        /**
         * @function addNode
         * @description 向 store 中添加一个新节点。
         *              添加节点后，会重新验证行为树的结构。
         * @param {BehaviorTreeNode} newNode - 要添加的新节点。
         */
        addNode: (newNode: BehaviorTreeNode) => {
        set((state) => {
            const newNodes = [...state.nodes, newNode as Node<NodeData>];
            // 类型断言：确保传入 validateTree 的 nodes 符合 BehaviorTreeNode[] 类型
            const newErrors = validateTree(newNodes as BehaviorTreeNode[], state.edges);
            return {
                nodes: newNodes,
                errors: newErrors,
            };
        });
        },
        /**
         * @function setSelectedNodeId
         * @description 设置当前选中的节点ID。
         * @param {string | null} nodeId - 选中的节点ID，如果没有选中则为 null。
         */
        setSelectedNodeId: (nodeId: string | null) => {
        set({ selectedNodeId: nodeId });
        },
        /**
         * @function updateNodeData
         * @description 更新指定节点的data属性。
         *              更新节点数据后，会重新验证行为树的结构。
         * @param {string} nodeId - 要更新的节点ID。
         * @param {Partial<NodeData>} newData - 要合并到节点data中的新数据。
         */
        updateNodeData: (nodeId: string, newData: Partial<NodeData>) => {
        set((state) => {
            const updatedNodes = state.nodes.map((node) =>
                node.id === nodeId
                    ? { ...node, data: { ...node.data, ...newData } }
                    : node
            );
            // 类型断言：确保传入 validateTree 的 nodes 符合 BehaviorTreeNode[] 类型
            const newErrors = validateTree(updatedNodes as BehaviorTreeNode[], state.edges);
            return {
                nodes: updatedNodes,
                errors: newErrors,
            };
        });
        },
        /**
         * @function applyLayout
         * @description 对行为树节点应用自动布局。
         *              调用 Dagre 工具函数，并用布局后的新位置更新节点状态。
         *              通过直接调用 `setNodes` 确保布局更新后触发 React Flow 的渲染和行为树验证。
         */
        applyLayout: () => {
        set((state) => {
            const layoutedNodes = getLayoutedElements(state.nodes, state.edges);
            // 直接调用 setNodes，利用其内部已有的更新和验证逻辑
            return {
                ...state,
                nodes: layoutedNodes,
                errors: validateTree(layoutedNodes as BehaviorTreeNode[], state.edges), // 确保验证被触发
            };
        });
        },
        /**
         * @function updateSettings
         * @description 更新编辑器设置。
         * @param {Partial<EditorSettings>} newSettings - 要更新的设置。
         */
        updateSettings: (newSettings: Partial<EditorSettings>) => {
        set((state) => ({
            settings: { ...state.settings, ...newSettings }
        }));
        },
    };
});